<template>
  <el-form
    v-if="showForm"
    ref="formLabels"
    :model="formData"
    :rules="rules"
    :dict-list="dictList"
    class="demo-formLabels"
    :label-width="labelWidth + 'px'"
    v-bind="$attrs"
    :label-position="labelPosition"
    @submit.native.prevent>
    <el-row class="el-row-flex">
      <template v-for="(item, index) in formLabels">
        <el-col
          v-if="!item.hidden"
          :ref="item"
          :key="index"
          :span="item.span ? item.span : 12"
          :class="item.position ? 'col-bg' : ''"
          :style="{
            zIndex: `${maxIndex - index}`,
            position: item.position ? 'sticky' : '',
            // position: item.position ? (top > 0 ? 'sticky' : '') : '',
            top: `${item.top - top}px`,
          }">
          <!-- top: `${top > 0 ? top : item.top - firstTop}px`, -->
          <!-- left: item.position ? (top < 0 ? (index % 2 == 0 ? '35%' : '') : '') : '',
            width: item.position ? (top > 0 ? '' : '34%') : '',
            marginTop: top < 0 ? (!item.position ? '210px' : '') : '', -->
          <!-- top: `${item.top - top - firstTop}px`, -->
          <!--   文本框   -->
          <el-form-item
            :ref="item.field"
            :label="item.label"
            :prop="item.field"
            :label-position="labelPosition"
            :label-width="item.labelWidth || labelWidth + 'px'">
            <span v-if="item.showPrefix" class="el-input__prefix">C</span>
            <el-input-number
              v-if="item.type == 'InputNumber'"
              v-model="formData[item.field]"
              :clearable="true"
              :placeholder="getPlaceHolder(item)"
              v-bind="item.attrs"
              :disabled="item.disabled"
              @blur="handleEvent($event, item.field)" />
            <el-input
              v-if="item.type == 'input'"
              v-model="formData[item.field]"
              :clearable="true"
              :placeholder="item.placeHolder || getPlaceHolder(item)"
              v-bind="item.attrs"
              :maxlength="item.maxlength || 100"
              :disabled="item.disabled"
              @blur="handleEvent($event, item.field)" />
            <!--   密码框   -->
            <el-input
              v-if="item.type == 'password'"
              v-model="formData[item.field]"
              :clearable="true"
              show-password
              :placeholder="getPlaceHolder(item)"
              :disabled="item.disabled"
              v-bind="item.attrs"
              @change="handleEvent($event, item.field, 'change')" />
            <!--   下拉框   -->
            <el-select
              v-if="item.type == 'select'"
              v-model="formData[item.field]"
              :clearable="true"
              filterable
              :placeholder="getPlaceHolder(item)"
              :disabled="item.disabled"
              v-bind="item.attrs"
              :multiple="item.multiple"
              style="width: 100%"
              @focus="setMinWidth"
              @change="handleEvent($event, item.field, 'change')">
              <el-option
                v-for="(el, i) in dictList[item.list]"
                :key="i"
                :label="el.label"
                :value="el.value"
                :title="el.label"
                :style="{ 'max-width': maxWidth + 2 + 'px' }" />
            </el-select>
            <!--   级联选择器   -->
            <el-cascader
              v-if="item.type == 'cascader'"
              v-model="formData[item.field]"
              v-bind="item.attrs"
              :popper-append-to-body="false"
              :placeholder="getPlaceHolder(item)"
              :options="dictList[item.list]"
              :clearable="true"
              :props="item.props"
              style="width: 100%"
              filterable
              @expand-change="expandChange"
              @change="handleEvent($event, item.field, 'change')" />
            <!--   开关   -->
            <el-switch
              v-if="item.type == 'switch'"
              v-model="formData[item.field]"
              :disabled="item.disabled"
              v-bind="item.attrs"
              :active-value="item.activeValue"
              :inactive-value="item.inactiveValue"
              @change="handleEvent($event, item.field, 'change')" />
            <!--   复选框   -->
            <el-checkbox-group
              v-if="item.type == 'checkbox'"
              v-model="formData[item.field]"
              style="width: 100%"
              @change="handleEvent($event, item.field, 'change')">
              <el-checkbox
                v-for="el in dictList[item.list]"
                :key="el.value"
                :label="el.label"
                :disabled="item.disabled"
                v-bind="item.attrs"
                >{{ el.label }}</el-checkbox
              >
            </el-checkbox-group>
            <!--   单选框   -->
            <el-radio-group
              v-if="item.type == 'radio'"
              v-model="formData[item.field]"
              v-bind="item.attrs"
              style="width: 100%"
              @change="handleEvent($event, item.field, 'change')">
              <el-radio
                v-for="el in dictList[item.list]"
                :key="el.value"
                :label="el.value"
                :disabled="item.disabled"
                v-bind="item.attrs"
                style="margin-bottom: 5px"
                >{{ el.label }}</el-radio
              >
            </el-radio-group>
            <!--   文本域   -->
            <el-input
              v-if="item.type == 'textarea'"
              v-model="formData[item.field]"
              type="textarea"
              :clearable="true"
              style="width: 100%"
              :placeholder="getPlaceHolder(item)"
              :maxlength="item.maxlength"
              v-bind="item.attrs"
              :show-word-limit="item.limit || false"
              @blur="handleEvent($event, item.field)" />
            <!--   计数器   -->
            <el-input-number
              v-if="item.type == 'number'"
              v-model="formData[item.field]"
              :min="0"
              :placeholder="getPlaceHolder(item)"
              style="width: 100%"
              controls-position="right"
              v-bind="item.attrs"
              @change="handleEvent($event, item.field, 'change')" />
            <!--   日期时间选择器   -->
            <el-date-picker
              v-if="item.type == 'dateTime'"
              v-model="formData[item.field]"
              style="width: 100%"
              type="datetime"
              :value-format="item.format"
              :placeholder="getPlaceHolder(item)"
              @change="handleEvent($event, item.field, 'change')" />
            <!-- 日期区间选择器 -->
            <el-date-picker
              v-if="item.type == 'datetimerange'"
              v-model="formData[item.field]"
              style="width: 100%"
              type="datetimerange"
              value-format="yyyy-MM-dd HH:mm:ss"
              :start-placeholder="startPlace(item)"
              :end-placeholder="endPlace(item)"
              @change="handleEvent($event, item.field, 'change')" />
            <!--    日期选择器    -->
            <el-date-picker
              v-if="item.type == 'datePicker'"
              v-model="formData[item.field]"
              style="width: 100%"
              type="date"
              :placeholder="getPlaceHolder(item)"
              :value-format="item.format"
              @change="handleEvent($event, item.field, 'change')" />
            <!--    日期区间选择器    -->
            <el-date-picker
              v-if="item.type == 'dateRange'"
              v-model="formData[item.field]"
              style="width: 100%"
              type="daterange"
              :value-format="item.format || 'yyyy-MM-dd HH:mm:ss'"
              range-separator="至"
              :picker-options="item.TimePickerOptions"
              :start-placeholder="startPlace(item)"
              :end-placeholder="endPlace(item)"
              @change="handleEvent($event, item.field, 'change')" />
            <treeselect
              v-if="item.type == 'treeselect'"
              v-model="formData[item.field]"
              :options="dictList[item.list]"
              :normalizer="item.normalizer"
              :append-to-body="true"
              :autocheckparent="item.autocheckparent"
              :placeholder="getPlaceHolder(item)"
              :disabled="item.disabled"
              noResultsText="无匹配数据"
              @select="handleEvent($event, item.field, 'change')" />
            <!--    插槽    -->
            <slot v-if="item.type == 'slot'" :name="'filter-' + item.field" />
          </el-form-item>
        </el-col>
      </template>
    </el-row>
    <el-form-item style="flex: 1; display: flex; justify-content: end">
      <slot />
    </el-form-item>
    <div v-show="!btnHidden" style="width: 100%; text-align: right">
      <el-button type="primary" @click="handleFormSubmit('formLabels')">保 存</el-button>
      <el-button @click="resetForm('formLabels')">取消</el-button>
    </div>
  </el-form>
</template>

<script>
import Treeselect from '@riophae/vue-treeselect'
export default {
  components: { Treeselect },
  props: {
    labelPosition: {
      type: String,
      default: 'left',
    },
    data: {
      type: Object,
      default() {
        return {}
      },
    },
    formLabels: {
      type: Array,
      default() {
        return []
      },
    },
    fieldList: {
      type: Array,
      default() {
        return []
      },
    },
    rules: {
      type: Object,
      default() {
        return {}
      },
    },
    dictList: {
      type: Object,
      default() {
        return {}
      },
    },
    labelWidth: {
      type: String,
      default() {
        return '100'
      },
    },
    btnHidden: {
      type: Boolean,
      default() {
        return false
      },
    },
    isPlace: {
      type: Boolean,
      default() {
        return false
      },
    },
    top: {
      type: Number,
      default() {
        return 0
      },
    },
  },
  data() {
    return {
      // trueData: JSON.parse(JSON.stringify(this.data)),
      showForm: true,
      maxIndex: 100,
      defaultKeyList: [],
      maxWidth: null,
    }
  },

  computed: {
    formData: {
      get() {
        return this.data
      },
      set() {},
    },
  },
  watch: {
    formData: {
      handler(newVal) {},
      deep: true,
      immediate: true,
    },
    formLabels: {
      handler(val) {
        if (val) {
          this.$nextTick(() => {
            for (var i = 0; i < val.length - 1; i++) {
              const item = val[i]
              if (!item.hidden) {
                if (this.$refs[item][i]) {
                  const value = this.$refs[item][i].$el.getBoundingClientRect().top
                  item.top = value
                }
              }
            }
            this.$emit('getTop', val)
            this.$forceUpdate()
          })
        }
      },
      deep: true,
      immediate: true,
    },
  },
  mounted() {
    this.$nextTick(() => {
      // 添加这段代码
      const $el = document.querySelectorAll('.el-cascader-panel .el-cascader-node[aria-owns]')
      Array.from($el).map((item) => item.removeAttribute('aria-owns'))
    })
  },
  methods: {
    // 解决级联选死机问题
    expandChange() {
      this.$nextTick(() => {
        // 添加这段代码
        const $el = document.querySelectorAll('.el-cascader-panel .el-cascader-node[aria-owns]')
        Array.from($el).map((item) => item.removeAttribute('aria-owns'))
      })
    },
    /**
     *定义占位符
     * @param item
     */

    getPlaceHolder(item) {
      if (this.isPlace) {
        return ' '
      }
      let placeHolder = ''
      if (item?.attrs?.placeholder) {
        placeHolder = `${item.attrs.placeholder}`
        return placeHolder
      }
      if (item.type === 'input' || item.type === 'number' || item.type === 'textarea' || item.type === 'password') {
        placeHolder = `请输入${item.label}`
      } else if (item.type === 'select' || item.type === 'cascader') {
        if (item?.attrs?.placeholder) {
          placeHolder = `${item.attrs.placeholder}`
        } else {
          placeHolder = `请选择${item.label}`
        }
      } else if (item.type === 'date') {
        placeHolder = `请选择${item.label}`
      } else if (item.type === 'dateTime' || item.type === 'datetimerange') {
        placeHolder = `请选择日期时间`
        console.log(placeHolder)

        // placeHolder = `请选择${item.label}`
      } else if (item.type === 'datePicker') {
        placeHolder = `请选择日期`
        // placeHolder = `请选择${item.label}`
      }

      return placeHolder
    },
    startPlace(item) {
      if (this.isPlace) {
        return ' '
      }
      var placeHolder = '请选择开始日期'
      return placeHolder
    },
    endPlace(item) {
      if (this.isPlace) {
        return ' '
      }
      var placeHolder = '请选择结束日期'
      return placeHolder
    },
    /**
     * 提交 校验
     * @returns {Promise<unknown>}
     */
    handleFormSubmit(formName) {
      const _self = this
      return new Promise((resolve) => {
        _self.$refs[formName]
          .validate()
          .then(() => {
            resolve(_self.formData)
            this.$emit('handleSubmitEvent', _self.formData)
          })
          .catch(() => {
            _self.$message({
              message: '请完善表单！',
              type: 'error',
            })
          })
      })
    },
    /**
     * 取消
     * */
    resetForm(formName) {
      this.$refs[formName].resetFields()
      this.$emit('handleCancel')
    },
    // 清除验证   在打开弹框事件以及弹框的确认和取消事件 调用此方法
    clearcheck(formName) {
      if (this.$refs[formName]) {
        this.$nextTick(() => {
          this.$refs[formName].clearValidate()
        })
      }
    },
    resetOne(formName, name) {
      this.$refs[formName].validateField(name)
    },
    /** formData赋值：处理响应式丢失 */
    setFormData(target, val) {
      this.$set(this.formData, target, val)
    },
    clearName(formName, propName) {
      if (this.$refs[formName]) {
        this.$nextTick(() => {
          this.$refs[formName].clearValidate(propName)
        })
      }
    },

    /**
     * @func 事件处理
     * @desc 📝
     */
    handleEvent(event, val, change) {
      console.log(event, val, change)
      this.defaultKeyList.indexOf(val) < 0 && this.defaultKeyList.push(val)
      const obj = {
        value: change === 'change' ? event : event.target.value,
        field: val,
      }
      this.$forceUpdate()
      this.$emit('handleEvent', obj)
    },
    // 设置下拉框的宽度
    setMinWidth(val) {
      //  webkit内核
      if (val.srcElement) {
        this.maxWidth = val.srcElement.clientWidth
      }
      //  火狐内核
      if (val.target) {
        this.maxWidth = val.target.clientWidth
      }
    },
  },
}
</script>
<style lang="scss" scoped>
.demo-formLabels {
  // height: 100%;
}
#app.dark-theme {
  .col-bg {
    // background-color: #3b8bff19;
    background: url('../../assets/images/dark/bg.png') no-repeat;
  }
}
.col-bg {
  background-color: #fff;
}
::v-deep .el-select-dropdown__item {
  width: calc(100% - 10px);
  display: inline-block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.el-form-item {
  margin: 10px;
}

.el-form {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
}
.el-input__prefix {
  z-index: 100;
}
.el-row-flex {
  width: 100%;
  flex-wrap: wrap;
  display: flex;
}
::v-deep .el-cascader {
  width: 100% !important;
}
#app ~ .el-select-dropdown {
  .el-select-dropdown__item {
    max-width: inherit !important;
  }
}
</style>
